home *** CD-ROM | disk | FTP | other *** search
/ Sound Fx / Sound Fx.iso / Software / UNZIPED / SBPLY254 / SOURCE.ZIP / SB.C < prev    next >
C/C++ Source or Header  |  1996-07-04  |  11KB  |  499 lines

  1. /***************************************************************************/
  2. /* sb.c  -- Routines Sound Blaster Card & DIGPak Drivers                   */
  3. /* Copyright (c) 1995 John A. Ball                                         */
  4. /*                                                                         */
  5. /* This source is available for your own personal use only! You may make   */
  6. /* any changes you wish but please do not distribute modified source code. */
  7. /* Please notify me of any errors or improvements.                         */
  8. /*                                                                         */
  9. /* by John A. Ball   July 4, 1996                                          */
  10. /***************************************************************************/
  11.  
  12. #include <stdio.h>
  13. #include <dos.h>
  14. #include <errno.h>
  15. #include <stdlib.h>
  16. #include <fcntl.h>
  17. #include <sys\types.h>
  18. #include <sys\stat.h>
  19. #include <io.h>
  20. #include <malloc.h>
  21. #include <string.h>
  22. #include <sound.h>
  23. #include <graph.h>
  24.  
  25.  
  26. #define SB_ADDRESS      0x210           /* starting i/o address for SB */
  27. #define TRUE 1
  28. #define NOCOMPRESS 100
  29.  
  30. struct SNDSTRUC snd;
  31. extern int debug;
  32. extern int verbose;
  33. extern int shell;
  34. extern int sb_info;
  35. extern struct CARD_INFO card_info;
  36. extern int volume;
  37. extern int compression;
  38. extern int magnitude;
  39. extern int default_bits;
  40. extern int stop;
  41. extern int repeat;
  42. extern int error;
  43. extern int multi_error;
  44. extern int conversion_table;
  45. extern unsigned int play_rate;
  46. extern unsigned int pitch;
  47. extern char _far **fbuffer;
  48. extern unsigned int dma_size;
  49.  
  50. int sb_address=0;
  51. int *psb;
  52.  
  53. int sb_card(void);
  54. int find_sb(void);
  55. int get_sb_info(void);
  56. int reset_sb(int address);
  57. void show_card_info(void);
  58. int speaker(int state);
  59. void delay(char tc, int period);
  60. int dacplay(char _far *fbuffer,int k,int frequency,int mode,int volume,int channels);
  61. int digplay(struct SNDSTRUC _far *sndplay);
  62. void show_dac_error(int error);
  63. int find_digpak(void);
  64. int get_card_type(void);
  65. int get_version(void);
  66. int play_block(struct SOUND *hp, int source_handle);
  67.  
  68.  
  69. int  sb_card(void)
  70. {
  71.     int error=0;
  72.     int blaster=0;
  73.  
  74.     psb=&sb_info;
  75.  
  76.     error=get_sb_info();
  77.     blaster=psb[4];
  78.     if(error > 0){
  79.       printf("Error in Sound Blaster Environment %i\n",error);
  80.       switch(error)
  81.        {
  82.       case 10:
  83.          printf("A (Address ie A220) Parameter not found!\n");
  84.          break;
  85.       case 20:
  86.          printf("I (Irq ie I5) Parameter not found!\n");
  87.          break;
  88.       case 30:
  89.          printf("D (DMA ie D1) Parameter not found!\n");
  90.          break;
  91.       case 40:
  92.          printf("T (Type ie T3) Parameter not found!\n");
  93.          break;
  94.        }
  95.        blaster=find_sb();
  96.       }
  97.     else{
  98.       if((error < 0) && debug)
  99.         printf("No BLASTER parameters found in environment\n");
  100.       if(error < 0){
  101.         blaster=find_sb();
  102.       }
  103.  
  104.       if(!error){
  105.        error=reset_sb(blaster);
  106.        if(error){
  107.         blaster=find_sb();
  108.         printf("Environment BLASTER=A (Address) parameter is not correct.\n");
  109.        }
  110.       }
  111.       if(blaster){
  112.        psb[4]=blaster;
  113.       }
  114.     }
  115.     if(blaster){
  116.       if(reset_sb(blaster))
  117.         printf("Sound Blaster not responding to reset!\n");
  118.       card_info.io_addr=blaster;
  119.       sb_address=blaster;
  120.     }
  121.     return(blaster);
  122. }
  123.  
  124. /* Make sure Sound Blaster Available */
  125.  
  126. int find_sb(void)
  127. {
  128.     int blaster=0;
  129.  
  130.     _asm{
  131.          push bx
  132.          mov bx,0
  133.     h0:
  134.          mov al,1
  135.          mov dx,SB_ADDRESS
  136.          add dx,6
  137.          add dx,bx
  138.          out dx,al
  139.          in al,dx
  140.          in al,dx
  141.          in al,dx
  142.          in al,dx
  143.          mov al,0
  144.          out dx,al
  145.          add dx,4
  146.          mov cx,0ffffh
  147.     h1:
  148.          in al,dx
  149.          cmp al,0aah
  150.          je h2
  151.          loop h1
  152.          add bx,010h
  153.          cmp bx,050h
  154.          jle h0
  155.          mov ax,0
  156.          mov blaster,ax
  157.          jmp h3
  158.     h2:
  159.          mov ax,SB_ADDRESS
  160.          add ax,bx
  161.          mov blaster,ax
  162.     h3:  pop bx
  163.     }
  164.     if(debug && blaster)printf("Found Sound Blaster Board @ %x\n",blaster);
  165.     return(blaster);
  166. }
  167.  
  168. int get_sb_info(void)
  169. {
  170.    char *pe;
  171.    char v[80];
  172.    char *pv;
  173.    char b[80];
  174.    int i=0;
  175.    int error=0;
  176.  
  177.    pe=getenv("BLASTER");
  178.    if(pe!=NULL){
  179.      strcpy( v, pe );
  180.  
  181.      pv=strpbrk(v,"A");
  182.      if(pv!=NULL){
  183.        if(debug)printf("Environment parameter BLASTER=%s\n",pv);
  184.        pv++;
  185.        i=0;
  186.       while(( *pv != '\x20' || '\x0' ) && i<80)
  187.       {
  188.     b[i]=*pv++;
  189.     i++;
  190.       }
  191.       b[i]='\x0';
  192.       i=atoi(b);
  193.       i=(i-200)/10;
  194.       psb[4]=0x200 + i*16;
  195.      }
  196.     else error=10;
  197.  
  198.      pv=strpbrk(v,"I");
  199.      if(pv!=NULL){
  200.        pv++;
  201.        i=0;
  202.        while((*pv != ' ' || '\0') && i<80)
  203.        {
  204.     b[i]=*pv++;
  205.     i++;
  206.        }
  207.        b[i]='\0';
  208.        psb[1]=atoi(b);
  209.      }
  210.      else error=20;
  211.  
  212.      pv=strpbrk(v,"D");
  213.      if(pv!=NULL){
  214.        pv++;
  215.        i=0;
  216.        while((*pv != ' ' || '\0') && i<80)
  217.        {
  218.     b[i]=*pv++;
  219.     i++;
  220.        }
  221.        b[i]='\0';
  222.        psb[6]=atoi(b);
  223.      }
  224.      else error=30;
  225.  
  226.      pv=strpbrk(v,"T");
  227.      if(pv!=NULL){
  228.        pv++;
  229.        i=0;
  230.        while((*pv != ' ' || '\0') && i<80)
  231.        {
  232.     b[i]=*pv++;
  233.     i++;
  234.        }
  235.        b[i]='\0';
  236.        psb[7]=atoi(b);
  237.      }
  238.      else error=40;
  239.  
  240.    return(error);
  241.    }
  242.    else return(-1);
  243. }
  244.  
  245. int speaker(int state)
  246. {
  247.     if(card_info.type==BLASTER){
  248.     _asm{
  249.     mov bx,state
  250.     mov dx,sb_address
  251.     add dx,0ch
  252.     mov cx,0ffffh
  253. g_s:    in al,dx
  254.     and al,080h
  255.     je s_ok
  256.     loop g_s
  257.     mov ax,1
  258.     jmp s_end
  259. s_ok:   cmp bx,0
  260.     je speak_off
  261.     mov al,0d1h
  262.     out dx,al
  263.     mov ax,0
  264.     jmp s_end
  265. speak_off:
  266.     mov al,0d3h
  267.     out dx,al
  268.     mov ax,0
  269. s_end:
  270.     }
  271.     }
  272. }
  273.  
  274. int reset_sb(int address)
  275. {
  276.     _asm{
  277.          mov bx,0
  278.     h0:
  279.          mov al,1
  280.          mov dx,address
  281.          add dx,6
  282.          out dx,al
  283.          in al,dx
  284.          in al,dx
  285.          in al,dx
  286.          in al,dx
  287.          mov al,0
  288.          out dx,al
  289.          add dx,4
  290.          mov cx,0ffffh
  291.     h1:
  292.          in al,dx
  293.          cmp al,0aah
  294.          je h6
  295.          loop h1
  296.          mov ax,1                   ;error
  297.          jmp h3
  298.     h6:
  299.          add dx,4
  300.          mov cx,0ffffh
  301.     h4:
  302.          in al,dx
  303.          OR AL,AL
  304.          JNS H2
  305.          LOOP H4
  306.          mov ax,1                   ;error
  307.          jmp h3
  308.     h5:
  309.          add bx,010h
  310.          cmp bx,050h
  311.          jle h0
  312.          mov ax,1                   ;error
  313.          jmp h3
  314.     h2:
  315.          mov ax,0                   ;ok
  316.     h3:
  317.     }
  318. }
  319. void show_card_info(void)
  320. {
  321.     int *psb_info;
  322.     int version=0;
  323.  
  324.     psb_info=&sb_info;
  325.  
  326.     if(debug && (card_info.type==BLASTER))printf("Sound Blaster DSP version %X I/O %x IRQ %i DMA %i Type %i\n"
  327.     ,psb_info[5],psb_info[4],psb_info[1],psb_info[6],psb_info[7]);
  328.     if(debug && card_info.type==DIGPAK){
  329.        version=get_version();
  330.        if(version==0)version=100;
  331.        printf("DIGPAK Driver version %.2f installed!\n",(float)version/100);
  332.     }
  333.     if(debug && card_info.type==PCSPEAKER)printf("No sound card found using pc speaker!\n");
  334. }
  335.  
  336. void delay(char tc, int period)
  337. {
  338.       if(card_info.type==BLASTER)error=sbdelay(tc,period);
  339. }
  340.  
  341. int dacplay(char _far *fbuffer,int k,int frequency,int mode,int volume,int channels)
  342. {
  343.      int error=0;
  344.      int flag=0;
  345.  
  346.      if(card_info.type==BLASTER){
  347.      mode=(mode & 0xfffe);
  348.  
  349.      switch(mode)
  350.      {
  351.      case 0:
  352.        error=sbdma(fbuffer,k,frequency,0,volume,channels);
  353.        break;
  354.      case ADPCM4:
  355.        error=sbdma(fbuffer,k,frequency,1,volume,channels);
  356.        break;
  357.      case ADPCM26:
  358.        error=sbdma(fbuffer,k,frequency,2,volume,channels);
  359.        break;
  360.      case ADPCM2:
  361.        error=sbdma(fbuffer,k,frequency,3,volume,channels);
  362.        break;
  363.      case BIT8_S:
  364.        error=sbdma(fbuffer,k,frequency,4,volume,channels);
  365.        break;
  366.      default:
  367.        if(shell)printf("\n          Type of Compression not supported!          \n");
  368.        else if(verbose)printf("Type of Compression not supported!\n");
  369.        multi_error=TRUE;
  370.        error=NOCOMPRESS;
  371.        break;
  372.      }
  373.      }
  374.      else if(card_info.type==DIGPAK){
  375.  
  376.      snd.sound=fbuffer;
  377.      snd.sndlen=k;
  378.      snd.IsPlaying=&flag;
  379.      snd.frequency=frequency;
  380.      mode=(mode & 0xfffe);
  381.  
  382.      switch(mode)
  383.      {
  384.      case 0:
  385.      case BIT8_S:
  386.        error=digplay(&snd);
  387.        break;
  388.      default:
  389.        if(shell)printf(" Type of Compression not supported!\n");
  390.        else if(verbose)printf("Type of Compression not supported!\n");
  391.        multi_error=TRUE;
  392.        error=NOCOMPRESS;
  393.        break;
  394.      }
  395.      }
  396.      return(error);
  397. }
  398.  
  399. void show_dac_error(int error)
  400. {
  401.     if(shell && (card_info.type!=PCSPEAKER)){
  402.       _settextcolor(14);
  403.       _settextposition(24,10);
  404.       _outtext("                                   ");
  405.       _settextposition(23,1);
  406.     }
  407.  
  408.       if(card_info.type==BLASTER)printf("Problem with Sound Blaster ");
  409.       switch(error)
  410.       {
  411.         case 1:
  412.           printf("Error 1 DMA already in use!\n");
  413.           break;
  414.         case 2:
  415.           printf("Error 2 IRQ not responding!\n");
  416.           break;
  417.         case 3:
  418.           printf("Error 3 DSP not responding!\n");
  419.           break;
  420.         case 4:
  421.           printf("Error 4 Could not read DSP version!\n");
  422.           break;
  423.         case 5:
  424.           printf("Error 5 DMA channel not working (must be 0, 1, or 3)!\n");
  425.           break;
  426.         case 6:
  427.           printf("Error 6 I (IRQ) parameter in environment is not correct!\n");
  428.           break;
  429.         case 7:
  430.           printf("Error 7 IRQ not valid (must be 2, 3, 5, 7, or 10)!\n");
  431.           break;
  432.         case 8:
  433.           printf("Error 8 number of samples is zero!\n");
  434.           break;
  435.         case NOCOMPRESS:
  436.           break;
  437.         default:
  438.           printf("Unknown error! %i\n",error);
  439.           break;
  440.       }
  441. }
  442.  
  443. /* Check for a Sound Card */
  444.  
  445. int get_card_type(void)
  446. {
  447.     int type=PCSPEAKER;
  448.     if(sb_card())type=BLASTER;
  449.     if(check_digpak())type=DIGPAK;
  450.     return(type);
  451. }
  452.  
  453. int check_digpak(void)
  454. {
  455.  
  456.     _asm{
  457.     push ds
  458.     push si
  459.     mov si,66h*4            ;get vector number
  460.     xor ax,ax               ;zero
  461.     mov ds,ax               ;point it there
  462.     lds si,[si]             ;get address of ivec
  463.     or si,si                ;zero?
  464.     jz ciout                ;exit if zero
  465.     sub si,6                ;point back to identifier
  466.     cmp [si],0494dh         ; 'IM' midi driver?
  467.     jne nex
  468.     cmp [si+2],04944h    ;'ID' full midi driver identity string?
  469.     jne nex
  470. ;   ok, a MIDI driver is loaded at this address.
  471.     mov ax,0701h            ;digitized sound capabilities request
  472.     int 66h
  473.     or ax,ax
  474.     jnz dok                 ;yes,
  475.     jz ciout                ;no
  476. nex:    cmp [si],454bh
  477.     jne ciout
  478.     cmp [si+2],4e52h
  479.     je dok
  480. ciout:  xor ax,ax               ;zero driver
  481.     jmp ext
  482. dok:    mov ax,1
  483. ext:    pop si
  484.     pop ds
  485.     }
  486. }
  487.  
  488. int get_version(void)
  489. {
  490.     _asm{
  491.     mov bx,0
  492.     mov ax,0689h
  493.     int 66h
  494.     mov ax,bx
  495.     }
  496. }
  497.  
  498.  
  499.